<?php

class TemplateExporter
{
	var $db_info = null;
	var $output_dir_path = null;
	var $mappings = array();
	var $do_confirm = null;
	var $db_link = null;
	
	var $sites_to_export = null;
	var $all_sites = null;
	
	var $importer = null; // a reference to a TemplateImporter, used to validate mappings
	
	/**
	 *
	 */
	function __construct($db_info, $output_dir_path, $importer, $sites_to_export=array("all"), $do_confirm=false)
	{
		if (empty($db_info) || empty($output_dir_path) || empty($importer) || empty($sites_to_export))
		{
			exit("[TemplateExporter] error: missing one or more required parameters\n");
		}
		
		if (!file_exists($output_dir_path))
		{
			exit("[TemplateExporter] error: template output directory does not exist: $output_dir_path\n");		
		}

		if (!is_writable($output_dir_path))
		{
			exit("[TemplateExporter] error: template output directory exists but is not writable: $output_dir_path\n");		
		}

		$this->db_info = $db_info;
		$this->output_dir_path = $output_dir_path;
		$this->importer = $importer;
		$this->do_confirm = $do_confirm;
		
		$this->sites_to_export = $sites_to_export;
		
		print("Connecting to host: {$db_info['hostname']}, with user {$db_info['username']} (pass: {$db_info['password']})\n");
		
		$this->db_link = mysql_connect($db_info['hostname'], $db_info['username'], $db_info['password'])
			or die('[TemplateExporter] error: could not connect to server: ' . mysql_error());

		print("Selecting database: {$db_info['database']}\n\n");
			
		mysql_select_db($db_info['database']) 
			or die('[TemplateExporter] error: could select datbase: ' . mysql_error());
	}
	
	/**
	 *
	 */
	function export()
	{
		$query = "SHOW COLUMNS FROM exp_templates LIKE 'site_id'";
		$field_rows = $this->get_query_rows($query);
		$has_site_id = (sizeof($field_rows) > 0);
		$site_order = ($has_site_id ? ", exp_templates.site_id" : "");

		if ($has_site_id)
		{
			$this->all_sites = $this->get_sites();
			print("All available sites:\n");
			print_r($this->all_sites);
			print("\n");
			
			print("Exporting sites:\n");
			print_r($this->sites_to_export);
			print("\n");
			
			if (sizeof($this->sites_to_export) > 0 && $this->sites_to_export[0] != "" && $this->sites_to_export[0] != 'all' && $this->sites_to_export[0] != '*')
			{
				$export_sites = array_intersect($this->all_sites, $this->sites_to_export);
				$export_site_ids = array_keys($export_sites);
				
				$site_clause = " AND exp_templates.site_id IN ('".implode("','", $export_site_ids)."') ";
			}
		}
		
		$query = "SELECT * FROM exp_templates, exp_template_groups ".
				 "WHERE exp_templates.group_id = exp_template_groups.group_id $site_clause ".
				 "ORDER BY group_name, template_name $site_order";
				 
		print("$query\n");//TMP
		
		$template_rows = $this->get_query_rows($query);
		
		if (sizeof($template_rows) == 0)
		{
			exit('[TemplateExporter] error: exp_templates table was empty');
		}
		
		$groups = $this->get_template_groups();
		
		// check language site templates
		if (sizeof($this->sites_to_export) == 1 && sizeof($this->all_sites) > 1)
		{
			$template_rows = $this->check_language_template_embeds($template_rows);
		}
		
		// output the template files and the mappings
		foreach ($template_rows as $row)
		{
			$map = array();
			
			$template_path = $this->output_dir_path;
			
			$site_id = $row['site_id'];
			$template_name = $row['template_name'];
			if (!empty($site_id))
			{
				$site_name = $this->all_sites[$site_id];
				$map['site'] = $site_name;
				$template_path .= "/$site_name";
				
				if ($this->do_confirm) // create the site directory
				{
					if (!file_exists($template_path))
					{
						print("Creating site directory: $template_path\n");
						mkdir($template_path) or die("[TemplateExporter] error: could not create directory: $template_path\n");
					}
				}
			}
			
			$group_id = $row['group_id'];
			$group_name = $groups[$group_id];
			
			$template_path .= "/$group_name";
			
			if ($this->do_confirm) // create the template group directory
			{
				if (!file_exists($template_path))
				{
					print("Creating template group directory: $template_path\n");
					mkdir($template_path) or die("[TemplateExporter] error: could not create directory: $template_path\n");
				}
			}
			
			$map['template_name'] = $template_name;
			$map['template_group'] = $group_name;
			$map['allow_php'] = $row['allow_php'];
			$map['php_parse_location'] = $row['php_parse_location'];
			
			$template_type = $row['template_type'];
			$map['template_type'] = $template_type;
			switch ($template_type)
			{
				case webpage :
					$extension = ($row['allow_php'] == 'y' ? '.php' : '.html');
					break;
				default :
					$extension = ".$template_type";
					break;
			}
			
			if (preg_match("/.+\..+/", $template_name)) // already has file extension
			{
				$extension = "";
			}
			
			$template_path .= "/$template_name" . $extension;
			$map['path'] = $template_path;
			
			$ignore_file = true;
			$this->importer->validate_mapping($map, $ignore_file); // quits with an error if there is a problem
			$this->mappings[] = $map;
			
			$template_data = $row['template_data'];
			if ($this->do_confirm) // output the template file
			{
				print("Creating template file for real: $template_path");
				print(" [size: ".(strlen($template_data) / 1024)." Kb]\n");;
				print("Mapping:\n");
				print_r($map);
				print("\n");
				$error = "[TemplateExporter] error: could not output template file: $template_path";
				if (strlen($template_data) > 0)
				{
					file_put_contents($template_path, $template_data) or die($error);
				}
				else
				{
					touch($template_path) or die($error);
				}
			}
			else // show mapping (includes which file would be written) 
			{
				print("Template mapping preview:\n");
				print_r($map);
				print("\n");
			}
			
//			print("importer:\n");//TMP
//			print_r($importer);//TMP
		}
		
		$mappings_path = $this->output_dir_path . "/" . $this->db_info['database'] . "_mappings.php";
		
		if ($this->do_confirm)
		{
			print("Writing mappings file: $mappings_path\n");
			$success = $this->output_mappings_file($this->mappings, $mappings_path);
			if (!$success)
			{
				exit("[TemplateExporter] error: could not output mappings file\n");
			}
		}
		else
		{
			print("Preview mappings file: $mappings_path\n");
		}
		
		print("\n".sizeof($template_rows)." templates processed.\n");//TMP
	}
	
	function check_language_template_embeds($template_rows)
	{
		foreach ($template_rows as $row)
		{
			//get same template from all language sites
			$shell_site_id = $row['site_id'];
			$shell_template_name = $row['template_name'];
			$shell_template_group = $row['group_name'];
			
			$query = "SELECT * FROM exp_templates, exp_template_groups ".
				 	"WHERE exp_templates.group_id = exp_template_groups.group_id ".
					"AND exp_templates.site_id != $shell_site_id ".
					"AND exp_templates.template_name = '$shell_template_name' ".
					"AND exp_template_groups.group_name = '$shell_template_group' ".
					"ORDER BY group_name, template_name, exp_templates.site_id ";
			
			$lang_template_rows = $this->get_query_rows($query);
			
			if (sizeof($lang_template_rows) > 0)
			{
				//check template matches pointer page pattern
				foreach ($lang_template_rows as $lang_row)
				{
					$shell_site_name = $this->all_sites[$shell_site_id];
					$lang_site_name = $this->all_sites[$lang_row['site_id']];
					$lang_data = $lang_row['template_data'];
					
					if($lang_data != "")
					{
						$regex = "/\{embed\=".$shell_site_name."\:([^\/].*)\/([^\{\}].*)\}/";
						
						if(!preg_match($regex, $lang_data))
						{
							//add row to template rows
							print("Adding language site custom template: $lang_site_name - $shell_template_group/$shell_template_name\n");
							
							$template_rows[] = $lang_row;
						}
					}
				}
			}
		}
		
		return $template_rows;
	}
	
	/**
	 *
	 */
	function output_mappings_file($mappings, $path)
	{
		if (sizeof($mappings) == 0)
		{
			return false;
		}
	
		$template_types = array();
	
		$inner_content = "";
	
		$inner_content .= "\n\n\t\$mappings = array(\n";
		
		$seen_groups = array();
		
		foreach ($mappings as $map)
		{
			$group_name = $map['template_group'];
			if (!isset($seen_groups[$group_name]))
			{
				$inner_content .= "\n\t\t// $group_name";
			}
			$seen_groups[$group_name] = $group_name;
		
			$inner_content .= "\n\t\tarray(\n\t\t\t";
			
			$i = 0;
			foreach ($map as $key => $value)
			{
				if ($key == 'template_type')
				{
					$new_value = 'TYPE_' . strtoupper($value);
					$template_types[$new_value] = $value;
					$value = $new_value;
				}
				else if ($key == 'php_parse_location')
				{
					$value = ($value == 'o' ? 'PARSE_OUTPUT' : 'PARSE_INPUT');
				}
				else
				{
					$value = "'$value'";
				}
			
				if ($key == 'site' && preg_match("/shell/", $value)) // if this is a shell site mapping
				{
					$inner_content .= "'create_pointer_pages' => \$do_create_pointers, ";
					$i++;
				}
			
				$inner_content .= "'$key' => $value, ";
				if ($i > 0 && $i % 4 == 0)
				{
					$inner_content .= "\n\t\t\t";
				}
				$i++;
			}
			
			$inner_content .= "\n\t\t),\n";
		}
		
		$inner_content .= "\n\t);\n";

		$content = "<?php\n\n/* Generated by the Template Exporter at ".date('d-m-Y H:i:s')." */\n\n";

		foreach ($template_types as $key => $value)
		{
			$content .= "\tdefine($key, '$value');\n"; 
		}
		$content .= "\n\tdefine(PARSE_INPUT, 'i');\n";
		$content .= "\tdefine(PARSE_OUTPUT, 'o');\n";
		
		$content .= "\n\t\$do_create_pointers = true;\n";

		$content .= $inner_content;
		
		$content .= "\n\n?>";
		
/*		eval("?>" . $content) or $message = ("[TemplateExporter] error: mappings file content did not evaluate nicely as valid PHP\n"); */
		
		if (!empty($message))
		{
			print($message);
		}
		
		$byte_count = file_put_contents($path, $content) or print("[TemplateExporter] error: could not write mappings file\n");		
		
		$success = ($byte_count > 0);

		return $success;
	}
	
	
	function get_sites() // fetch site data
	{
		$query = "SELECT * FROM exp_sites"; 
		$site_rows = $this->get_query_rows($query);
		$sites = array();
		if (sizeof($site_rows) > 0)
		{
			foreach ($site_rows as $row)
			{
				$id = $row['site_id'];
				$sites[$id] = $row['site_name'];
			}
		}	
		
		return $sites;
	}

	function get_template_groups() // fetch tempalte group data
	{
		$query = "SELECT * FROM exp_template_groups";
		$group_rows = $this->get_query_rows($query);
		$groups = array();
		if (sizeof($group_rows) > 0)
		{
			foreach ($group_rows as $row)
			{
				$id = $row['group_id'];
				$groups[$id] = $row['group_name'];
			}
		}	
		
		return $groups;
	}
	
	/**
	 *
	 */
	function get_query_rows($query)
	{
		$rows = array();
	
		$result = mysql_query($query, $this->db_link) 
			or die('[TemplateExporter] error: Query failed: ' . mysql_error());

		if (mysql_num_rows($result) > 0)
		{
			while (($row = mysql_fetch_assoc($result)))
			{
				$rows[] = $row;
			}
		}
		
		return $rows;
	}
	
	/**
	 *
	 */
	function execute_query($query)
	{
		$result = mysql_query($query, $this->db_link) 
			or die('[TemplateExporter] error: Query failed: ' . mysql_error());		
			
		$affected = mysql_affected_rows($this->db_link);

		return $affected;
	}
}


?>